import { useEffect, useState, useCallback } from 'react'
import { WebContainer } from '@webcontainer/api'

export interface FileSystemNode {
  name: string
  type: 'file' | 'directory'
  content?: string
  children?: FileSystemNode[]
}

export function useWebContainer() {
  const [webcontainer, setWebcontainer] = useState<WebContainer | null>(null)
  const [isLoading, setIsLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [terminalOutput, setTerminalOutput] = useState<string[]>([])
  const [previewUrl, setPreviewUrl] = useState<string | null>(null)

  // 初始化 WebContainer
  useEffect(() => {
    const initWebContainer = async () => {
      try {
        setIsLoading(true)
        const instance = await WebContainer.boot()
        setWebcontainer(instance)
        
        // 监听端口变化
        instance.on('server-ready', (port, url) => {
          setPreviewUrl(url)
        })
        
        setError(null)
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Failed to initialize WebContainer')
      } finally {
        setIsLoading(false)
      }
    }

    initWebContainer()
  }, [])

  // 写入文件
  const writeFile = useCallback(async (path: string, content: string) => {
    if (!webcontainer) return
    
    try {
      await webcontainer.fs.writeFile(path, content)
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to write file')
    }
  }, [webcontainer])

  // 读取文件
  const readFile = useCallback(async (path: string): Promise<string | null> => {
    if (!webcontainer) return null
    
    try {
      const content = await webcontainer.fs.readFile(path, 'utf-8')
      return content
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to read file')
      return null
    }
  }, [webcontainer])

  // 创建目录
  const createDirectory = useCallback(async (path: string) => {
    if (!webcontainer) return
    
    try {
      await webcontainer.fs.mkdir(path, { recursive: true })
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to create directory')
    }
  }, [webcontainer])

  // 运行命令
  const runCommand = useCallback(async (command: string, args: string[] = [], waitForCompletion: boolean = false) => {
    if (!webcontainer) return
    
    try {
      const process = await webcontainer.spawn(command, args)
      
      // 正确处理输出流
      const reader = process.output.getReader()
      
      const readOutput = async () => {
        try {
          while (true) {
            const { done, value } = await reader.read()
            if (done) break
            
            // 简化的数据处理方式
            let text: string = ''
            
            try {
              if (typeof value === 'string') {
                text = value
              } else if (value) {
                // 尝试使用 TextDecoder 解码
                text = new TextDecoder().decode(value as any)
              }
            } catch (decodeError) {
              // 如果解码失败，尝试转换为字符串
              try {
                text = String(value || '')
              } catch {
                text = '[Binary data]'
              }
            }
            
            if (text) {
              setTerminalOutput(prev => [...prev, text])
            }
          }
        } catch (err) {
          console.error('Error reading output:', err)
        }
      }
      
      // 启动输出读取
      readOutput()
      
      // 如果需要等待完成，则等待进程退出
      if (waitForCompletion) {
        await process.exit
      }
      
      return process
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to run command')
    }
  }, [webcontainer])

  // 安装依赖
  const installDependencies = useCallback(async () => {
    if (!webcontainer) return
    
    setTerminalOutput(prev => [...prev, '$ npm install'])
    await runCommand('npm', ['install'], true) // 等待安装完成
  }, [webcontainer, runCommand])

  // 启动开发服务器
  const startDevServer = useCallback(async () => {
    if (!webcontainer) return
    
    setTerminalOutput(prev => [...prev, '$ npm run dev'])
    await runCommand('npm', ['run', 'dev'])
  }, [webcontainer, runCommand])

  // 初始化项目文件
  const initializeProject = useCallback(async () => {
    if (!webcontainer) return

    const files = {
      'package.json': {
        file: {
          contents: JSON.stringify({
            name: 'online-ide-project',
            version: '1.0.0',
            type: 'module',
            scripts: {
              dev: 'vite',
              build: 'vite build',
              preview: 'vite preview'
            },
            dependencies: {
              'vite': '^5.0.0'
            }
          }, null, 2)
        }
      },
      'index.html': {
        file: {
          contents: `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Online IDE Project</title>
</head>
<body>
    <div id="app">
        <h1>Hello from Online IDE!</h1>
        <p>Edit the files to see changes in real-time.</p>
    </div>
    <script type="module" src="/main.js"></script>
</body>
</html>`
        }
      },
      'main.js': {
        file: {
          contents: `console.log('Hello from Online IDE!');

// Add your JavaScript code here
document.addEventListener('DOMContentLoaded', () => {
    const app = document.getElementById('app');
    
    const button = document.createElement('button');
    button.textContent = 'Click me!';
    button.addEventListener('click', () => {
        alert('Hello from the online IDE!');
    });
    
    app.appendChild(button);
});`
        }
      },
      'style.css': {
        file: {
          contents: `body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 20px;
    background-color: #f0f0f0;
}

#app {
    max-width: 800px;
    margin: 0 auto;
    background: white;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

h1 {
    color: #333;
    text-align: center;
}

button {
    background-color: #007acc;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 16px;
    margin-top: 20px;
}

button:hover {
    background-color: #005a9e;
}`
        }
      }
    }

    try {
      await webcontainer.mount(files)
      setTerminalOutput(prev => [...prev, 'Project initialized successfully!'])
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to initialize project')
    }
  }, [webcontainer])

  return {
    webcontainer,
    isLoading,
    error,
    terminalOutput,
    previewUrl,
    writeFile,
    readFile,
    createDirectory,
    runCommand,
    installDependencies,
    startDevServer,
    initializeProject,
    clearTerminal: () => setTerminalOutput([]),
    clearError: () => setError(null)
  }
}